home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / pseudoDoc / gatherHeaderDoc.pl < prev    next >
Encoding:
Perl Script  |  2001-06-23  |  10.1 KB  |  276 lines

  1. #! /usr/bin/perl -w
  2. #
  3. # Script name: gatherHeaderDoc
  4. # Synopsis:     Finds all HeaderDoc generated docs in an input
  5. #        folder and creates a top-level HTML page to them
  6. #
  7. # Author: Matt Morse (matt@apple.com)
  8. # Last Updated: $Date: 2001/03/29 03:02:19 $
  9. # Copyright (c) 1999 Apple Computer, Inc.  All Rights Reserved.
  10. # The contents of this file constitute Original Code as defined in and are
  11. # subject to the Apple Public Source License Version 1.1 (the "License").
  12. # You may not use this file except in compliance with the License.  Please
  13. # obtain a copy of the License at http://www.apple.com/publicsource and
  14. # read it before using this file.
  15. #
  16. # This Original Code and all software distributed under the License are
  17. # distributed on an TAS ISU basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  18. # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  19. # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
  20. # FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the License for
  21. # the specific language governing rights and limitations under the
  22. # License.
  23. #
  24. # $Revision: 1.3 $
  25. ######################################################################
  26. use Cwd;
  27. use File::Find;
  28. use File::Copy;
  29.  
  30. my $pathSeparator;
  31. my $isMacOS;
  32. my $scriptDir;
  33. my $framesetFileName;
  34. my $masterTOCFileName;
  35. BEGIN {
  36.     if ($^O =~ /MacOS/i) {
  37.             $pathSeparator = ":";
  38.             $isMacOS = 1;
  39.     } else {
  40.             $pathSeparator = "/";
  41.             $isMacOS = 0;
  42.     }
  43. }
  44.  
  45. use strict;
  46. use FindBin qw ($Bin);
  47. use lib "$Bin"."$pathSeparator"."Modules";
  48.  
  49. # Modules specific to gatherHeaderDoc
  50. use HeaderDoc::DocReference;
  51. use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc printArray printHash updateHashFromConfigFiles getHashFromConfigFile);
  52.  
  53. my $debugging = 1;
  54. ######################################## Design Overview ###################################
  55. # - We scan input directory for frameset files (index.html, by default).
  56. # - For each frameset file, we look for a special HTML comment (left by HeaderDoc)
  57. #   that tell us the name of the header/class and the type (header or cppclass). 
  58. # - We create a DocReference object to store this info, and also the path to the
  59. #   frameset file.
  60. # - We run through array of DocRef objs and create a master TOC based on the info
  61. # - Finally, we visit each TOC file in each frameset and add a "[Top]" link
  62. #   back to the master TOC.  [This is fragile in the current implementation, since
  63. #   we find TOCs based on searching for a file called "toc.html" in the frameset dir.
  64. ########################## Setup from Configuration File #######################
  65. my $localConfigFileName = "headerDoc2HTML.config";
  66. my $preferencesConfigFileName = "com.apple.headerDoc2HTML.config";
  67. my $homeDir = (getpwuid($<))[7];
  68. my $usersPreferencesPath = $homeDir.$pathSeparator."Library".$pathSeparator."Preferences";
  69. my @configFiles = ($Bin.$pathSeparator.$localConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName);
  70.  
  71. # default configuration, which will be modified by assignments found in config files.
  72. # The default values listed in this hash must be the same as those in the identical 
  73. # hash in headerDoc2HTML--so that links between the frameset and the masterTOC work.
  74. my %config = (
  75.     defaultFrameName => "index.html", 
  76.     masterTOCName => "MasterTOC.html"
  77. );
  78.  
  79. %config = &updateHashFromConfigFiles(\%config,\@configFiles);
  80.  
  81. if (defined $config{"defaultFrameName"}) {
  82.     $framesetFileName = $config{"defaultFrameName"};
  83. if (defined $config{"masterTOCName"}) {
  84.     $masterTOCFileName = $config{"masterTOCName"};
  85.  
  86. ########################## Input Folder and Files #######################
  87. my @inputFiles;
  88. my $inputDir;
  89.  
  90. if (($#ARGV == 0) && (-d $ARGV[0])) {
  91.     $inputDir = $ARGV[0];
  92.     $inputDir =~ s|(.*)/$|$1|; # get rid of trailing slash, if any
  93.     if ($inputDir !~ /^\//) { # not absolute path -- !!! should check for ~
  94.         my $cwd = cwd();
  95.         $inputDir = $cwd.$pathSeparator.$inputDir;
  96.     }
  97.     &find({wanted => \&getFiles, follow => 1}, $inputDir);
  98. } else {
  99.     die "You must specify a single input directory for processing.\n";
  100. }
  101. unless (@inputFiles) { print "No valid input files specified. \n\n";};
  102.  
  103. sub getFiles {
  104.     my $filePath = $File::Find::name;
  105.     my $fileName = $_;
  106.     
  107.     if ($fileName =~ /$framesetFileName/) {
  108.         push(@inputFiles, $filePath);
  109.     }
  110. }
  111. ########################## Find HeaderDoc Comments #######################
  112. my @headerFramesetRefs;
  113. my @classFramesetRefs;
  114.  
  115. my $oldRecSep = $/;
  116. undef $/; # read in files as strings
  117.  
  118. foreach my $file (@inputFiles) {
  119.     open (INFILE, "<$file") || die "Can't open $file: $!\n";
  120.     my $fileString = <INFILE>;
  121.     close INFILE;
  122.     if ($fileString =~ /<--\s+(headerDoc\s*=.*?)-->/) {
  123.         my $fullComment = $1;
  124.         my @pairs = split(/;/, $fullComment);
  125.         my $docRef = HeaderDoc::DocReference->new;
  126.         $docRef->path($file);
  127.         foreach my $pair (@pairs) {
  128.             my ($key, $value) = split(/=/, $pair);
  129.             $key =~ s/^\s+|\s+$//;
  130.             $value =~ s/^\s+|\s+$//;
  131.             SWITCH: {
  132.                 ($key =~ /headerDoc/) && 
  133.                     do {
  134.                         $docRef->type($value);
  135.                         last SWITCH;
  136.                     };
  137.                 ($key =~ /name/) && 
  138.                     do {
  139.                         $docRef->name($value);
  140.                         last SWITCH;
  141.                     };
  142.             }
  143.         }
  144.         my $tmpType = $docRef->type();
  145.         if ($tmpType eq "Header") {
  146.             push (@headerFramesetRefs, $docRef);
  147.         } elsif ($tmpType eq "CPPClass") {
  148.             push (@classFramesetRefs, $docRef);
  149.         } else {
  150.             my $tmpName = $docRef->name();
  151.             my $tmpPath = $docRef->path();
  152.             print "Unknown type '$tmpType' for document with name '$tmpName' and path '$tmpPath'\n";
  153.         }
  154.     }
  155. }
  156. $/ = $oldRecSep;
  157.  
  158. # create master TOC if we have any framesets
  159. if (scalar(@headerFramesetRefs) + scalar(@classFramesetRefs)) {
  160.     &printMasterTOC();
  161.     &addTopLinkToFramesetTOCs();
  162. } else {
  163.     print "gatherHeaderDoc.pl: No HeaderDoc framesets found--returning\n" if ($debugging); 
  164.     return;
  165. }
  166. exit 0;
  167.  
  168. ################### Print Navigation Page #######################
  169. sub printMasterTOC {
  170.     my $outputDir = $inputDir;
  171.     my $masterTOC = $outputDir.$pathSeparator. $masterTOCFileName;
  172.     my $headersLinkString= '';
  173.     my $classesLinkString = '';
  174.     my $fileString;
  175.     my $localDebug = 0;
  176.     
  177.     # get the HTML links to each header 
  178.     foreach my $ref (sort objName @headerFramesetRefs) {
  179.         my $name = $ref->name();
  180.         my $path = $ref->path();        
  181.         my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name);
  182.         $headersLinkString .= $tmpString;
  183.     }
  184.     print "\$headersLinkString is '$headersLinkString'\n" if ($localDebug);
  185.     
  186.     # get the HTML links to each class 
  187.     foreach my $ref (sort objName @classFramesetRefs) {
  188.         my $name = $ref->name();
  189.         my $path = $ref->path();        
  190.         my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name);
  191.         $classesLinkString .= $tmpString;
  192.     }
  193.     if (($localDebug) && length($classesLinkString)) {print "\$classesLinkString is '$classesLinkString'\n";};
  194.     
  195.     # put together header/footer with linkString--could use template
  196.     my $htmlHeader = "<html><head><title>Header Documentation</title></head><body bgcolor=\"#cccccc\"><h1>Header Documentation</h1><hr><br>\n";
  197.     my $headerSection = "<h2>Headers</h2>\n<blockquote>\n".$headersLinkString."\n</blockquote>\n";
  198.     my $classesSection = '';
  199.     if (length($classesLinkString)) {
  200.         $classesSection = "<h2>Classes</h2>\n<blockquote>\n".$classesLinkString."\n</blockquote>\n";
  201.     }
  202.     my $htmlFooter = "</body>\n</html>\n";
  203.     $fileString = $htmlHeader.$headerSection.$classesSection.$htmlFooter;
  204.     
  205.     # write out page
  206.     print "gatherHeaderDoc.pl: writing master TOC to $masterTOC\n" if ($localDebug);
  207.     open(OUTFILE, ">$masterTOC") || die "Can't write $masterTOC.\n";
  208.     print OUTFILE $fileString;
  209.     close OUTFILE;
  210. }
  211.  
  212. sub addTopLinkToFramesetTOCs {
  213.     my $masterTOC = $inputDir.$pathSeparator. $masterTOCFileName;
  214.     my $tocFileName = "toc.html";
  215.     my @allDocRefs;
  216.     push(@allDocRefs, @headerFramesetRefs);
  217.     push(@allDocRefs, @classFramesetRefs);
  218.     my $localDebug = 0;
  219.     
  220.     foreach my $ref (@allDocRefs) {
  221.         my $name = $ref->name();
  222.         my $type = $ref->type();
  223.         my $path = $ref->path();
  224.         my $tocFile = $path;                   # path to index.html
  225.         my $fsName = quotemeta($framesetFileName);
  226.         $tocFile =~ s/$fsName$/toc.html/;         # path to toc.html
  227.         
  228.         if (-e "$tocFile" ) {
  229.             my $oldRecSep = $/;
  230.             undef $/; # read in file as string
  231.             open(INFILE, "<$tocFile") || die "Can't read file $tocFile.\n";
  232.             my $fileString = <INFILE>;
  233.             close INFILE;
  234.             $/ = $oldRecSep;
  235.             
  236.             my $uniqueMarker = "headerDoc=\"topLink\"";
  237.             if ($fileString !~ /$uniqueMarker/) { # we haven't been here before
  238.                 my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC);
  239.                 my $topLink = "\n<font size=\"-2\"><a href=\"$relPathToMasterTOC\" target=\"_top\" $uniqueMarker>[Top]</a></font><br>\n";
  240.                 
  241.                 $fileString =~ s/(<body[^>]*>)/$1$topLink/i;
  242.             
  243.                 open (OUTFILE, ">$tocFile") || die "Can't write file $tocFile.\n";
  244.                 print OUTFILE $fileString;
  245.                 close (OUTFILE);
  246.             }
  247.         } elsif ($debugging) {
  248.             print "--> '$tocFile' doesn't exist!\n";
  249.             print "Cannot add [top] link for frameset doc reference:\n";
  250.             print "   name: $name\n";
  251.             print "   type: $type\n";
  252.             print "   path: $path\n";
  253.         }
  254.     }
  255. }
  256.  
  257. sub getLinkToFramesetFrom {
  258.     my $masterTOCFile = shift;
  259.     my $dest = shift;    
  260.     my $name = shift;    
  261.     my $linkString;
  262.     
  263.     my $relPath = &findRelativePath($masterTOCFile, $dest);
  264.     $linkString = "<a href=\"$relPath\" target =\"_top\">$name</a><br>\n"; 
  265.     return $linkString;
  266. }
  267.  
  268.  
  269. sub objName { # for sorting objects by their names
  270.     uc($a->name()) cmp uc($b->name());
  271. }
  272.